package cn.simon.free.redis.crud;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Maps;
import com.google.common.reflect.TypeToken;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.ParameterizedType;
import java.util.Map;

/**
 * @author simon
 * @date 2021/6/23 12:06
 * @copyright:
 * @modifier
 * @motto a no talent, people who have to study hard
 */
public class CommonConvert<T> {

    /**
     * 获取泛型
     */
    protected final Class<T> crudClass = (Class) ((ParameterizedType) TypeToken.of(this.getClass()).getRawType().getGenericSuperclass()).getActualTypeArguments()[0];

    protected final ObjectMapper mapper = new ObjectMapper();
    /**
     * 别名maps key value 都不能重复
     */
    protected final BiMap<Object, Object> hashFieldWithFieldAliasMaps = HashBiMap.create();
    /**
     * hashKey,构造方法中初始化时,只有前缀,调用具体的crud的时候,会拼写成完整的hashKey
     */
    protected String hashKeyPrefix;
    /**
     * hash 过期时间
     */
    protected long timeOut;

    /**
     * 新增对象maps
     *
     * @param writeMaps
     * @return
     */
    protected Map<Object, Object> convertWithWrite(Map<Object, Object> writeMaps) {
        Map<Object, Object> writeMap = Maps.newHashMapWithExpectedSize(writeMaps.size());
        writeMaps.forEach((key, value) -> writeMap.put(hashFieldWithFieldAliasMaps.getOrDefault(key, key), value));
        return writeMap;
    }

    /**
     * 真实对象(如果使用了别名,就需要映射成对象字段名)
     *
     * @param readMaps
     * @return
     */
    protected T convertWithRead(Map<Object, Object> readMaps) {
        if (CollectionUtils.isEmpty(readMaps)) {
            return null;
        }
        Map<Object, Object> readMap = Maps.newHashMapWithExpectedSize(readMaps.size());
        BiMap<Object, Object> inverseMaps = hashFieldWithFieldAliasMaps.inverse();
        readMaps.forEach((key, value) -> readMap.put(inverseMaps.getOrDefault(key, key), value));
        return mapper.convertValue(readMap, crudClass);
    }

}
